package service

import (
	"errors"
	"gorm.io/gorm"
	"time"
	"vrcm/src/vrcm/app/admin/models/comment"
	"vrcm/src/vrcm/app/admin/service/dto/comment"
	"vrcm/src/vrcm/common/actions"
	cDto "vrcm/src/vrcm/common/dto"
	"vrcm/src/vrcm/common/service"
)

type Comment struct {
	service.Service
}

// GetPage 获取Comment列表
func (e *Comment) GetPage(c *dto.CommentGetPageReq, list *[]comment.Comment, count *int64) error {
	var err error
	var data comment.Comment

	err = e.Orm.Model(&data).
		Scopes(
			cDto.MakeCondition(c.GetNeedSearch()),
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
		).
		Order("create_time desc").
		Find(list).Limit(-1).Offset(-1).
		Count(count).Error
	if err != nil {
		e.Log.Errorf("CommentService GetPage error:%s \r\n", err)
		return err
	}
	return nil
}

// Get 获取Comment对象
func (e *Comment) Get(d *dto.CommentGetReq, p *actions.DataPermission, model *comment.Comment) error {
	var data comment.Comment

	err := e.Orm.Model(&data).
		Scopes(
			actions.Permission(data.TableName(), p),
		).
		First(model, d.GetId()).Error
	if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
		err = errors.New("查看对象不存在或无权查看")
		e.Log.Errorf("Service GetComment error:%s \r\n", err)
		return err
	}
	if err != nil {
		e.Log.Errorf("db error:%s", err)
		return err
	}
	return nil
}
func (e *Comment) NoSpeak(c *dto.CommentInsertReq) error {
	var black comment.CommentBlack
	e.Orm.Model(comment.CommentBlack{}).Where("tenant_id =? and basic_id =? and account=?", c.TenantId, c.BasicId, c.Account).Find(&black)

	if black.Id > 0 {
		return errors.New("该用户已被禁言")
	}
	return nil
}

// Insert 创建Comment对象
func (e *Comment) Insert(c *dto.CommentInsertReq) error {
	var err error
	var data comment.Comment
	//var black comment.CommentBlack

	c.Generate(&data)
	err = e.Orm.Create(&data).Error
	if err != nil {
		e.Log.Errorf("CommentService Insert error:%s \r\n", err)
		return err
	}
	c.Id = data.Id
	return nil
}

// Update 修改Comment对象
func (e *Comment) Update(c *dto.CommentUpdateReq) error {
	var err error
	var data = comment.Comment{}
	e.Orm.First(&data, c.GetId())
	c.Generate(&data)

	db := e.Orm.Save(&data)
	if err = db.Error; err != nil {
		e.Log.Errorf("CommentService Save error:%s \r\n", err)
		return err
	}
	if db.RowsAffected == 0 {
		return errors.New("无权更新该数据")
	}
	return nil
}

// Remove 删除Comment
func (e *Comment) Remove(d *dto.CommentDeleteReq, p *actions.DataPermission) error {
	var data comment.Comment

	db := e.Orm.Model(&data).
		Scopes(
			actions.Permission(data.TableName(), p),
		).Delete(&data, d.GetId())
	if err := db.Error; err != nil {
		e.Log.Errorf("Service RemoveComment error:%s \r\n", err)
		return err
	}
	if db.RowsAffected == 0 {
		return errors.New("无权删除该数据")
	}
	return nil
}

// Review 审核
func (e *Comment) Review(d *dto.CommentReviewReq) error {
	tx := e.Orm.Begin()
	defer func() {
		if r := recover(); r != nil {
			e.Log.Errorf("Service Review error:%s \r\n", r)
			tx.Rollback()
		}
	}()
	if err := tx.Error; err != nil {
		return err
	}

	param := make(map[string]interface{})
	param["comment_state"] = d.CommentState
	param["update_time"] = time.Now().Unix()
	param["update_by"] = d.UpdateBy
	err := e.Orm.Model(&comment.Comment{}).Where("id =?", d.Id).Updates(param).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("Service Review error:%s \r\n", err)
		return err
	}

	var c comment.Comment
	tx.First(&c, d.Id)

	if d.CommentState == 4 {
		b := comment.CommentBlack{
			TenantId: c.TenantId,
			BasicId:  c.BasicId,
			Account:  c.Account,
		}
		b.CreateTime = time.Now().Unix()
		err := tx.Create(&b).Error
		if err != nil {
			tx.Rollback()
			e.Log.Errorf("Service Review error:%s \r\n", err)
			return err
		}
	}

	tx.Commit()
	return nil
}

// GetValidateComments 获取有效评论
func (e *Comment) GetValidateComments(d *dto.GetAllReviews) []comment.Comment {
	comments := make([]comment.Comment, 0, 20)
	var c comment.Comment
	if d.LastId <= 0 {
		e.Orm.Where("tenant_id =? and basic_id =? and comment_state = 3", d.TenantId, d.BasicId).
			Order("update_time desc").
			Limit(d.PageSize).
			Find(&comments)
		return comments
	}

	e.Orm.First(&c, d.LastId)
	e.Orm.Where("tenant_id =? and basic_id =? and comment_state = 3 and update_time<=? and id!=?", d.TenantId, d.BasicId, c.UpdateTime, c.Id).
		Order("update_time desc").
		Find(&comments).Limit(d.PageSize)

	return comments
}

// GetReplies 获取评论二级查询
func (e *Comment) GetReplies(d *dto.GetAllReplies) ([]comment.Comment, error) {

	// 查询该评论的所有回复
	results := make([]comment.Comment, 0, 5)
	db := e.Orm.Model(&comment.Comment{}).Where("tenant_id=? and bind_id=? and basic_id=?", d.TenantId, d.BindId, d.BasicId).Order("create_time desc")
	err := db.Find(&results).Error
	if err != nil {
		e.Log.Errorf("GetReplies:%s \r\n", err)
		return nil, err
	}

	parentMap := make([]comment.Comment, 0, 5)
	childMap := make(map[int][]comment.Comment)
	for _, v := range results {
		v := v
		if v.ParentId == 0 {
			parentMap = append(parentMap, v)
			//parentMap[v.Id] = v
			continue
		}
		t, ok := childMap[v.FirstId]
		if !ok {
			t = make([]comment.Comment, 0, 5)
		}
		t = append(t, v)
		childMap[v.FirstId] = t
	}

	//var pairs []comment.Comment
	//for _, v := range parentMap {
	//	pairs = append(pairs, v)
	//}
	//
	//// 对切片进行排序
	//sort.Slice(pairs, func(i, j int) bool {
	//	return pairs[i].CreateTime > pairs[j].CreateTime
	//})

	comments := make([]comment.Comment, 0, 5)
	for _, v := range parentMap {
		v := v
		v.Replies = make([]comment.Comment, 0, 5)
		child, ok1 := childMap[v.Id]
		if ok1 {
			v.Replies = append(v.Replies, child...)
		}
		comments = append(comments, v)
	}

	// 返回所有回复
	return comments, nil
}

func buildCommentTree(comments []*comment.Comment) []*comment.Comment {
	commentMap := make(map[int]*comment.Comment)
	var rootComments []*comment.Comment
	secondCommentMap := make(map[int]*comment.Comment)
	// 构建评论映射表
	for _, comment := range comments {
		commentMap[comment.Id] = comment
		//找到二级评论
		if comment.FirstId > 0 && comment.FirstId == comment.ParentId {
			_, ok := secondCommentMap[comment.FirstId]
			if !ok {
				secondCommentMap[comment.FirstId] = comment
			}
		}
	}

	// 将评论放入对应的父评论下面
	for _, comment := range comments {
		parentID := comment.ParentId
		if parentID == 0 {
			rootComments = append(rootComments, comment)
		}
		parentComment, ok := commentMap[parentID]
		if !ok {
			continue
		}
		//如果是子回复并且是二级子回复
		if comment.FirstId == comment.ParentId {
			parentComment.Replies = append(parentComment.Replies, *comment)
		} else {
			secondComment, ok1 := secondCommentMap[comment.FirstId]
			if ok1 {
				secondComment.Replies = append(secondComment.Replies, *comment)
			}
		}
	}

	return rootComments
}

// GetCommentList 获取评论列表平铺形式
func (e *Comment) GetCommentList(d *dto.GetCommentList, count *int64) ([]comment.Comment, error) {

	// 查询该评论的所有回复
	results := make([]comment.Comment, 0, 5)
	err := e.Orm.Model(&comment.Comment{}).
		Scopes(
			cDto.Paginate(d.GetPageSize(), d.GetPageIndex()),
		).
		Where("tenant_id=? and bind_id=? and user_name like ?", d.TenantId, d.BindId, "%"+d.UserName+"%").
		Order("create_time desc").
		Find(&results).Limit(-1).Offset(-1).
		Count(count).Error
	if err != nil {
		e.Log.Errorf("CommentService GetPage error:%s \r\n", err)
		return results, err
	}

	//parentMap := make([]comment.Comment, 0, 5)
	childMap := make(map[int][]comment.Comment)
	for _, v := range results {
		v := v
		//if v.ParentId == 0 {
		//	parentMap = append(parentMap, v)
		//	continue
		//}
		t, ok := childMap[v.FirstId]
		if !ok {
			t = make([]comment.Comment, 0, 5)
		}
		t = append(t, v)
		childMap[v.FirstId] = t
	}

	//var pairs []comment.Comment
	//for _, v := range parentMap {
	//	pairs = append(pairs, v)
	//}
	//
	//// 对切片进行排序
	//sort.Slice(pairs, func(i, j int) bool {
	//	return pairs[i].CreateTime > pairs[j].CreateTime
	//})

	comments := make([]comment.Comment, 0, 5)
	//for _, v := range parentMap {
	//	v := v
	//	v.Replies = make([]comment.Comment, 0, 5)
	//	child, ok1 := childMap[v.Id]
	//	if ok1 {
	//		v.Replies = append(v.Replies, child...)
	//	}
	//	comments = append(comments, v)
	//}

	for _, v := range results {
		v := v
		v.Replies = make([]comment.Comment, 0, 5)
		child, ok1 := childMap[v.Id]
		if ok1 {
			v.Replies = append(v.Replies, child...)
		}
		v.ReplyNum = len(v.Replies)
		comments = append(comments, v)
	}

	// 返回所有回复
	return comments, nil
}

func (e *Comment) DeleteComment(d *dto.DeleteComment) error {

	err := e.Orm.Model(&comment.Comment{}).Where("id in ?", d.Ids).Delete(&comment.Comment{}).Error
	if err != nil {
		e.Log.Errorf("DeleteComment:%s \r\n", err)
		return err
	}
	return nil
}
